﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace EventHandlerExtension.EventsExtension
{
    public delegate void EventExceptionHandler<T>(object sender, EventExceptionArgs<T> e) where T : EventArgs;

    public static partial class EventHandlerExtension
    {
        public static void Raise<T>(this EventHandler<T> handlers, object sender, T e) where T : EventArgs
        {
            if (handlers == null)
                return;

            handlers(sender, (T)e);
        }

        public static void RaiseSafe<T>(this EventHandler<T> handlers, object sender, T e) where T : EventArgs
        {
            if (handlers == null)
                return;

            List<Exception> exceptionList = new List<Exception>();

            IEnumerable<EventHandler<T>> handlerCast = handlers.GetInvocationList().Cast<EventHandler<T>>();
            foreach (EventHandler<T> handler in handlerCast)
            {
                try
                {
                    handler(sender, (T)e);
                }
                catch (Exception exception)
                {
                    exceptionList.Add(exception);
                }
            }

            if (exceptionList.Count > 0)
                throw new AggregateException(exceptionList);
        }


        public static void RaiseSafe<T>(this EventHandler<T> handler, object sender, T e, EventExceptionHandler<T> errorhandler) where T : EventArgs
        {
            if (handler == null)
                return;

            IEnumerable<EventHandler<T>> handlerInvocationList = handler.GetInvocationList().Cast<EventHandler<T>>();
            foreach (EventHandler<T> invocation in handlerInvocationList)
            {
                try
                {
                    invocation(sender, (T)e);
                }
                catch (Exception exception)
                {
                    errorhandler(handler, new EventExceptionArgs<T>(sender, invocation, (T)e, exception));
                }
            }
        }
    }
}
